package com.qianyitian.hope2.spider.lego;


import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSON;
import com.qianyitian.hope2.spider.external.NotifyClient;
import com.qianyitian.hope2.spider.util.Utils;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.text.MessageFormat.format;


@Component("legoSpider")
public class LegoSpider {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    LegoStorageService storageService;

    @Autowired
    NotifyClient notifyClient;

    public void updateStockStatus(List<LegoSet> list) {
        for (CountryEnum country : CountryEnum.values()) {
            processList(country, list);
        }
    }


    private void processList(CountryEnum country, List<LegoSet> list) {
        for (LegoSet legoSet : list) {
            ThreadUtil.sleep(1000);
            String url = MessageFormat.format(country.getPath(), legoSet.getCode());
            getStockStatus(country, url, legoSet);
            //store legoSet
            String content = JSON.toJSONString(legoSet);
            logger.info(content);

            String oldSetContent = storageService.get(legoSet.getCode(), country.getAbbreviation());
            if (oldSetContent != null) {
                LegoSet oldSet = JSON.parseObject(oldSetContent, LegoSet.class);
                LegoSet newSet = JSON.parseObject(content, LegoSet.class);
                if (Utils.stringEquals(oldSet.getBadge(), newSet.getBadge()) &&
                        Utils.stringEquals(oldSet.getStockStatus(), newSet.getStockStatus())) {
                } else {
                    //发通知
                    String info = htmlFormat(newSet, oldSet);
                    notifyMessage(info);
                }
            }
            storageService.store(legoSet.getCode(), country.getAbbreviation(), content);
        }
    }

    private boolean containsRetireKey(String content) {
        return content.toLowerCase().contains("retiring") || content.toLowerCase().contains("retired");
    }

    private String htmlFormat(LegoSet newSet, LegoSet oldSet) {
//<div class="highlight">42078 布加迪威龙</div>
//<div class="gray">原状：sold out / hard to find</div>
//<div class="normal">现状：retired product / hard to find</div>

        String messageFormat = "<div class=\"highlight\">{0}</div> " +
                "<div class=\"gray\">原状：{1}</div>" +
                "<div class=\"normal\">现状：{2}</div>";
        String[] array = newSet.getCode().split("-");
        String name = array[array.length - 1] + " " + newSet.getName() + " " + newSet.getCountry();
        String old = oldSet.getStockStatus() + " / " + oldSet.getBadge();
        String newInfo = newSet.getStockStatus() + " / " + newSet.getBadge();
        String content = MessageFormat.format(messageFormat, name, old, newInfo);
        return content;
    }

    public void notifyMessage(String info) {
        notifyClient.notifyAdminLego(info);
    }


    protected void getStockStatus(CountryEnum country, String url, LegoSet set) {
        try {
            Document doc = Jsoup.connect(url).get();
            Element badgeElement = doc.select("div.ProductOverviewstyles__ProductBadgesRow-sc-1a1az6h-0").first();
            Element productFlag = badgeElement.select("span.ProductBadge__StyledBadge-sc-1vris2w-0").first();
            if (productFlag != null) {
                set.setBadge(productFlag.text());
            }

            Element div = doc.select("div.ProductOverviewstyles__PriceAvailabilityWrapper-sc-1a1az6h-10").first();
            Element status = div.select("span.Markup__StyledMarkup-sc-nc8x20-0").first();
            if (status != null) {
                set.setStockStatus(status.text());
            }
            set.setCountry(country.getName());
            set.setCountryCode(country.getAbbreviation());
            set.setUpdateDate(LocalDate.now());
        } catch (Exception e) {
            logger.error(e.toString(), e);
        }
    }

    public String getZPrice(String url) {
        try {
            Document doc = Jsoup.connect(url).get();
            Element priceElement = doc.select(".a-offscreen").first();
            String price = priceElement.text();

            Element titleElement = doc.getElementById("productTitle");
            String name = titleElement.text();
            String info = name + " 价格是 " + price;
            return info;
        } catch (Exception e) {
            logger.error(e.toString(), e);
        }
        return null;
    }

    public void notifyAmazonCheapPrice(List<AmazonItem> allAmazonItem) {
        String urlTemplate = "https://www.amazon.cn/dp/{0}/";
        for (AmazonItem item : allAmazonItem) {
            ThreadUtil.sleep(1000);
            String url = MessageFormat.format(urlTemplate, item.getProductCode());
            getAmazonPrice(url, item);

            String content = JSON.toJSONString(item);
            logger.info(content);
            if (cheap(item)) {
                //发通知
                String info = htmlPriceNotifyFormat(item, url);
                notifyMessage(info);
            }
        }
    }

    private String htmlPriceNotifyFormat(AmazonItem item, String url) {
        String messageFormat = "<div class=\"highlight\">{0}</div> " +
                "<div class=\"gray\">价格：{1}</div>" +
                "<div class=\"normal\">网址：{2}</div>";
        String name = item.getName() + " " + item.getLegoCode();
        String price = Utils.double2Currency(item.getCurrentPrice());
        String site = url;
        String content = MessageFormat.format(messageFormat, name, price, site);
        return content;
    }

    private boolean cheap(AmazonItem item) {
        if (item.getCurrentPrice() <= 0.1) {
            return false;
        }
        if (item.getCurrentPrice() <= item.getNotifyPrice()) {
            return true;
        } else {
            return false;
        }
    }

    private Map getHeaders(String url) {
        Map headers = new HashMap();
        headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        headers.put("Accept-Encoding", "gzip, deflate");
        headers.put("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
        headers.put("Connection", "keep-alive");
        headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36");
        headers.put("Referer", url);
        headers.put("Host", "www.amazon.cn");
        headers.put("keep-alive", "keep-alive");
        return headers;
    }

    private void getAmazonPrice(String url, AmazonItem set) {
        try {
//
            Connection connection = Jsoup.connect(url);
            connection = connection.headers(getHeaders(url));
            Document doc = connection.get();
            Element priceElement = doc.select(".a-offscreen").first();
            String price = priceElement.text();
            price = price.substring(1, price.length() - 1);

            Element titleElement = doc.getElementById("productTitle");
            String name = titleElement.text();

            set.setName(name);
            price = price.replace(",", "");

            set.setCurrentPrice(Double.valueOf(price));
        } catch (Exception e) {
            logger.error(set.toString());
            logger.error(e.toString(), e);
        }
    }
}
